package org.fglxy.mockserver.netty.dynamic;

import java.util.List;

import org.fglxy.mockserver.entity.MockMessage;
import org.fglxy.mockserver.mock.IMockEnd;
import org.fglxy.mockserver.util.ProtoUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.protobuf.Message;

import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToMessageDecoder;

public class DynamicProtoDecode extends MessageToMessageDecoder<ByteBuf> {
	private Logger LOGGER = LoggerFactory.getLogger(DynamicProtoDecode.class);
	
	private IMockEnd end;
	
	public DynamicProtoDecode(IMockEnd end) {
		this.end = end;
	}
	
	@Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        super.channelActive(ctx);
        this.end.onConnect(ctx.channel());
    }
	/**
	 * 这个方法并不能被触发.断线还是得依赖心跳包
	 * @param ctx
	 * @throws Exception
	 */
	@Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        super.channelInactive(ctx);
        this.end.onConnectFinish(ctx.channel());
    }
	
	@Override
	protected void decode(ChannelHandlerContext ctx, ByteBuf msg, List<Object> out) throws Exception {
		//判断是否能读取头部
		if (!msg.isReadable(4)) {
			return;
		}
		//记录当前读取位置
		msg.markReaderIndex();
		int length = msg.readUnsignedShortLE();
		int cmdNo = msg.readUnsignedShortLE();
		//判断后续包体是否完整
		if (!msg.isReadable(length)) {
			msg.resetReaderIndex();
			return;
		}
		Message.Builder builder = ProtoUtils.getBuilderByCmdNo(end.getMockId(), cmdNo);
		byte[] datas = new byte[length];
		msg.readBytes(datas);
		LOGGER.info("cmdNo:{},builder:{}", cmdNo, builder);
		MockMessage mockMsg = null;
		if (builder != null) {
			builder = builder.mergeFrom(datas);
			Message proto = builder.build();
			mockMsg = new MockMessage(cmdNo, proto);
			LOGGER.info("找到消息协议类型,消息协议编号为 :{}消息体为:{}", cmdNo, proto);
		}
		else {
			mockMsg = new MockMessage(datas);
			mockMsg.setCmdNo(cmdNo);
		}
		LOGGER.info("接收到消息:cmdNo:{};length:{}", cmdNo, length);
		//通知终端接收消息
		this.end.onReceive(ctx.channel(), mockMsg);
	}

}
